5.01. Циклы
Циклы
Циклы: while, do...while, for, for...in, for...of, for await...of
Управление потоком: break, continue, return, throw
★ Цикл – многократно повторяемая процедура. Она может быть с известным количеством итераций и с неопределённым (бесконечным). То есть, либо мы знаем, когда начинать, сколько раз повторить, либо повторяем снова и снова, пока что-то не изменится.
for используется для определённого количества операций, с указанием начального значения, условия и шага каждой итерации:
for (начало; условие; шаг) {
// Тело цикла
}
Так, это похоже на функцию, где есть три выражения:
- начало задаёт начальное состояние цикла. Обычно здесь объявляется и инициализируется счётчик, который выполняется один раз перед началом. В начале можно как объявить переменную, так и использовать существующую;
- условие, которое проверяется перед каждой итерацией. Если это условие true (истинно), цикл выполняется, если false – цикл останавливается. Если условие пропустить, цикл будет выполняться бесконечно. Тут можно использовать любые логические выражения (
<,>,<=,=>и т.д.); - шаг, который выполняется после каждой итерации и меняет счётчик.
Пример:
for (let i = 0; i < 5; i++) {
console.log(i); // Выведет 0, 1, 2, 3, 4
}
Как это работает?
for– ключевое слово, указывающее на начало цикла;let i = 0– это начало, создание переменной с именем i и со значением 0;i < 5– это условие, и еслиi < 5то будет true и тело цикла выполняется;console.log(i)– это тело цикла, которое выводит в консоль значение переменнойi;i++- инкремент, когда значение увеличивается на 1;- повторная проверка будет выполняться снова и снова;
- если проверка true – цикл запускается снова, и снова выполняется тело.
Шаг — это выражение, которое изменяет значение переменной-счётчика на каждой итерации. Обычно он стоит на третьем месте в заголовке цикла for.
Как можно описать шаг?
| Шаг | Описание |
|---|---|
i++ | увеличивает i на 1 |
i-- | уменьшает i на 1 |
i += 2 | увеличивает i на 2 |
i -= 3 | уменьшает i на 3 |
i *= 2 | умножает i на 2 |
i /= 10 | делит i на 10 |
++ и -— это инкремент и декремент. Это специальные операторы для увеличения или уменьшения значения на 1. Бывают пост- и пре- операторы:
i++это постинкремент;++iэто преинкремент;i-—это постдекремент;--iэто предекремент. Разница между пре- и постформами важна только если результат используется сразу. Большинство этих операций (++,--,+=,-=,*=,/=) работают с числами , но JavaScript достаточно гибкий, и эти операторы могут работать и с другими типами данных.
Основное использование, конечно, числа, к примеру x+=3.
Со строками работает только +=, оператор работает как конкатенация строк:
let str = 'Привет';
str += ', мир!'; // 'Привет, мир!'
Но ++, --, -=, *= и т.д. со строками работать не будут корректно , так как JS попытается привести строку к числу, что может привести к NaN.
С объектами и массивами такие операции не имеют смысла. Поэтому грамотно подходите к выбору циклов - для других операций
Для работы с массивами лучше использовать forEach (в других языках он является полноценным циклом, тогда как в JavaScript это просто метод объектов-массивов), который озволяет перебрать все элементы массива , выполнив для каждого элемента заданную функцию (т.н. callback-функцию).
Он удобен и читабелен, особенно когда не нужно управлять индексами вручную, как в классическом for. Синтаксис у него таков:
array.forEach(function(element, index, array) {
// тело функции
});
Здесь мы вызываем функцию с параметрами:
- element - текущий элемент массива, обязательный;
- index - индекс текущего элемента (начинается с 0);
- array - сам массив, по которому идёт перебор.
Пример:
const fruits = ['яблоко', 'банан', 'груша'];
fruits.forEach(function(fruit) {
console.log(fruit);
});
// Вывод:
// яблоко
// банан
// груша
Функцию можно сделать стрелочной:
const numbers = [1, 2, 3];
numbers.forEach(num => console.log(num * 2));
// Вывод:
// 2
// 4
// 6
forEach не мутирует (не изменяет) исходный массив, break здесь не нужен (он его просто не поддерживает), а код будет более читабельным. Так что можно сказать, что в JS есть цикл foreach, но он просто метод для работы с массивами, для перебора элементов.
while используется, когда количество итераций неизвестно. Код будет выполняться то тех пор, пока условие true.
let i = 0;
while (i < 5) {
console.log(i); // Выведет 0, 1, 2, 3, 4
i++;
}
В данном случае, пока i не будет равным 5, будет выводиться значение i в консоль. Принцип такой же, как и в for, однако он не включает в себя объявление и цикл – всё, что нужно выполнять, выведено в тело цикла, в том числе i++ (инкремент) – «Пока условие истинно, делай вот это».
do…while отличается от while тем, что тело цикла выполнится хотя бы один раз, даже если условие false.
let i = 0;
do {
console.log(i); // Выведет 0
i++;
} while (i < 0); // Условие false, но цикл сработал 1 раз
Здесь заметно, что цикл начинается с ключевого слова do и заканчивается while. Это значит, что принцип такой – «Сделай вот это. Повторяй, пока условие истинно».
★ Таблица отличий циклов
| Цикл | Когда использовать | Особенности |
|---|---|---|
| for | Известно количество итераций | Компактный синтаксис |
| while | Неизвестно количество итераций | Может не выполниться ни разу |
| do…while | Проверка после итерации | Выполнится минимум 1 раз |
Операции выполняются в рамках функций, а циклы и условные операторы – части функций, словно инструменты. Каждая функция выполняется в соответствии с её телом. В общем случае JS работает в одном потоке, и долгие операции могут замораживать страницу, поэтому надо разбивать тяжёлые задачи на части. Однако, в ряде случаев, браузер «зависает» именно при ожидании результата выполнения функции. Тут мы подходим к асинхронности.